<!DOCTYPE html>



  


<html class="theme-next pisces use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">










<meta name="description" content="由于答案字数较多，已将此面试题分为上、下两级，此为上集。 八种基本数据类型的大小，以及他们的封装类 引用数据类型 Switch能否用string做参数 equals与==的区别 自动装箱，常量池 Object有哪些公用方法 Java的四种引用，强弱软虚，用到的场景 Hashcode的作用 HashMap的hashcode的作用 为什么重载hashCode方法？ ArrayList、LinkedLi">
<meta property="og:type" content="article">
<meta property="og:title" content="BTA 常问的 Java基础40道常见面试题及详细答案(上集)">
<meta property="og:url" content="https://mingmingv.gitee.io/2018/10/24/BTA-常问的-Java基础40道常见面试题及详细答案-上集/index.html">
<meta property="og:site_name" content="四 季">
<meta property="og:description" content="由于答案字数较多，已将此面试题分为上、下两级，此为上集。 八种基本数据类型的大小，以及他们的封装类 引用数据类型 Switch能否用string做参数 equals与==的区别 自动装箱，常量池 Object有哪些公用方法 Java的四种引用，强弱软虚，用到的场景 Hashcode的作用 HashMap的hashcode的作用 为什么重载hashCode方法？ ArrayList、LinkedLi">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2018-10-25T01:49:48.832Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="BTA 常问的 Java基础40道常见面试题及详细答案(上集)">
<meta name="twitter:description" content="由于答案字数较多，已将此面试题分为上、下两级，此为上集。 八种基本数据类型的大小，以及他们的封装类 引用数据类型 Switch能否用string做参数 equals与==的区别 自动装箱，常量池 Object有哪些公用方法 Java的四种引用，强弱软虚，用到的场景 Hashcode的作用 HashMap的hashcode的作用 为什么重载hashCode方法？ ArrayList、LinkedLi">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://mingmingv.gitee.io/2018/10/24/BTA-常问的-Java基础40道常见面试题及详细答案-上集/">





  <title>BTA 常问的 Java基础40道常见面试题及详细答案(上集) | 四 季</title>
  








</head>

<body itemscope="" itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope="" itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">四 季</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            标签
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope="" itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://mingmingv.gitee.io/2018/10/24/BTA-常问的-Java基础40道常见面试题及详细答案-上集/">

    <span hidden itemprop="author" itemscope="" itemtype="http://schema.org/Person">
      <meta itemprop="name" content="四 季">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="四 季">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">BTA 常问的 Java基础40道常见面试题及详细答案(上集)</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2018-10-24T12:41:34+08:00">
                2018-10-24
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="由于答案字数较多，已将此面试题分为上、下两级，此为上集。"><a href="#由于答案字数较多，已将此面试题分为上、下两级，此为上集。" class="headerlink" title="由于答案字数较多，已将此面试题分为上、下两级，此为上集。"></a>由于答案字数较多，已将此面试题分为上、下两级，此为上集。</h1><ol>
<li>八种基本数据类型的大小，以及他们的封装类</li>
<li>引用数据类型</li>
<li>Switch能否用string做参数</li>
<li>equals与==的区别</li>
<li>自动装箱，常量池</li>
<li>Object有哪些公用方法</li>
<li>Java的四种引用，强弱软虚，用到的场景</li>
<li>Hashcode的作用</li>
<li>HashMap的hashcode的作用</li>
<li>为什么重载hashCode方法？</li>
<li>ArrayList、LinkedList、Vector的区别</li>
<li>String、StringBuffer与StringBuilder的区别</li>
<li>Map、Set、List、Queue、Stack的特点与用法</li>
<li>HashMap和HashTable的区别</li>
<li>JDK7与JDK8中HashMap的实现</li>
<li>HashMap和ConcurrentHashMap的区别，HashMap的底层源码</li>
<li>ConcurrentHashMap能完全替代HashTable吗</li>
<li>为什么HashMap是线程不安全的</li>
<li>如何线程安全的使用HashMap</li>
<li>多并发情况下HashMap是否还会产生死循环</li>
</ol>
<h2 id="八种基本数据类型的大小，以及他们的封装类"><a href="#八种基本数据类型的大小，以及他们的封装类" class="headerlink" title="八种基本数据类型的大小，以及他们的封装类"></a>八种基本数据类型的大小，以及他们的封装类</h2><p>八种基本数据类型：int、short、float、double、long、boolean、byte、char。<br>封装类分别是：Integer、Short、Float、Double、Long、Boolean、Byte、Character。</p>
<h3 id="引用数据类型"><a href="#引用数据类型" class="headerlink" title="引用数据类型"></a>引用数据类型</h3><p>引用数据类型是由类的编辑器定义的，他们是用于访问对象的。这些变量被定义为不可更改的特定类型。<br>例如：Employee， Puppy 等等</p>
<ul>
<li>类对象和数组变量就是这种引用数据类型。</li>
<li>任何引用数据类型的默认值都为空。</li>
<li>一个引用数据类型可以被用于任何声明类型和兼容类型的对象。</li>
</ul>
<h3 id="Switch能否用string做参数"><a href="#Switch能否用string做参数" class="headerlink" title="Switch能否用string做参数"></a>Switch能否用string做参数</h3><p>jdk7之前 switch 只能支持 byte、short、char、int 这几个基本数据类型和其对应的封装类型。<br>switch后面的括号里面只能放int类型的值，但由于byte，short，char类型，它们会?自动?转换为int类型（精精度小的向大的转化），所以它们也支持。<br>jdk1.7后 整形，枚举类型，字符串都可以。<br>原理：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">switch (expression)  // 括号里是一个表达式，结果是个整数&#123;</span><br><span class="line">  <span class="keyword">case</span> constant1:   // <span class="keyword">case</span> 后面的标号，也是个整数</span><br><span class="line">     group of statements 1;</span><br><span class="line">     <span class="built_in">break</span>;</span><br><span class="line">  <span class="keyword">case</span> constant2:</span><br><span class="line">     group of statements 2;</span><br><span class="line">     <span class="built_in">break</span>;</span><br><span class="line">  ...</span><br><span class="line">  default:</span><br><span class="line">     default group of statements</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>jdk1.7后，整形，枚举类，字符串都可以。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">public class TestString &#123;</span><br><span class="line"></span><br><span class="line">    static String string = <span class="string">"123"</span>;</span><br><span class="line">    public static void main(String[] args) &#123;</span><br><span class="line">        switch (string) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"123"</span>:</span><br><span class="line">            System.out.println(<span class="string">"123"</span>);</span><br><span class="line">            <span class="built_in">break</span>;</span><br><span class="line">        <span class="keyword">case</span> <span class="string">"abc"</span>:</span><br><span class="line">            System.out.println(<span class="string">"abc"</span>);</span><br><span class="line">            <span class="built_in">break</span>;</span><br><span class="line">        default:</span><br><span class="line">            System.out.println(<span class="string">"defauls"</span>);</span><br><span class="line">            <span class="built_in">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="为什么jdk1-7后又可以用string类型作为switch参数呢？"><a href="#为什么jdk1-7后又可以用string类型作为switch参数呢？" class="headerlink" title="为什么jdk1.7后又可以用string类型作为switch参数呢？"></a>为什么jdk1.7后又可以用string类型作为switch参数呢？</h3><p>其实，jdk1.7并没有新的指令来处理switch string，而是通过调用switch中string.hashCode,将string转换为int从而进行判断。</p>
<h3 id="equals与-的区别"><a href="#equals与-的区别" class="headerlink" title="equals与==的区别"></a>equals与==的区别</h3><p>使用==比较原生类型如：boolean、int、char等等，使用equals()比较对象。</p>
<ol>
<li>==是判断两个变量或实例是不是指向同一个内存空间。 equals是判断两个变量或实例所指向的内存空间的值是不是相同。</li>
<li>==是指对内存地址进行比较。 equals()是对字符串的内容进行比较。</li>
<li>==指引用是否相同。 equals()指的是值是否相同。</li>
</ol>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">public static void main(String[] args) &#123;</span><br><span class="line"></span><br><span class="line">        String a = new String(<span class="string">"ab"</span>); // a 为一个引用</span><br><span class="line">        String b = new String(<span class="string">"ab"</span>); // b为另一个引用,对象的内容一样</span><br><span class="line">        String aa = <span class="string">"ab"</span>; // 放在常量池中</span><br><span class="line">        String bb = <span class="string">"ab"</span>; // 从常量池中查找</span><br><span class="line"></span><br><span class="line">        System.out.println(aa == bb); // <span class="literal">true</span></span><br><span class="line">        System.out.println(a == b); // <span class="literal">false</span>，非同一对象</span><br><span class="line">        System.out.println(a.equals(b)); // <span class="literal">true</span></span><br><span class="line">        System.out.println(42 == 42.0);  // <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) &#123;</span><br><span class="line">    Object obj1 = new Object();</span><br><span class="line">    Object obj2 = new Object();</span><br><span class="line">    System.out.println(obj1.equals(obj2));//<span class="literal">false</span></span><br><span class="line">    System.out.println(obj1==obj2);//<span class="literal">false</span></span><br><span class="line">    obj1=obj2;</span><br><span class="line">    System.out.println(obj1==obj2);//<span class="literal">true</span></span><br><span class="line">    System.out.println(obj2==obj1);//<span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="自动装箱，常量池"><a href="#自动装箱，常量池" class="headerlink" title="自动装箱，常量池"></a>自动装箱，常量池</h3><p>自动装箱 在jdk?1.5之前，如果你想要定义一个value为100的Integer对象，则需要如下定义：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Integer i = new Integer(100);</span><br><span class="line"></span><br><span class="line">int intNum1 = 100; //普通变量</span><br><span class="line">Integer intNum2 = intNum1; //自动装箱</span><br><span class="line">int intNum3 = intNum2; //自动拆箱</span><br><span class="line">Integer intNum4 = 100; //自动装箱</span><br></pre></td></tr></table></figure>
<blockquote>
<p>上面的代码中，intNum2为一个Integer类型的实例，intNum1为Java中的基础数据类型，将intNum1赋值给intNum2便是自动装箱；而将intNum2赋值给intNum3则是自动拆箱。<br>八种基本数据类型： <strong>boolean byte char shrot int long float double ,所生成的变量相当于常量。</strong><br>基本类型包装类：<strong>Boolean Byte Character Short Integer Long Float Double。</strong></p>
</blockquote>
<h3 id="自动拆箱和自动装箱定义："><a href="#自动拆箱和自动装箱定义：" class="headerlink" title="自动拆箱和自动装箱定义："></a>自动拆箱和自动装箱定义：</h3><p>自动装箱是将一个java定义的基本数据类型赋值给相应封装类的变量。 拆箱与装箱是相反的操作，自动拆箱则是将一个封装类的变量赋值给相应基本数据类型的变量。</p>
<h3 id="Object有哪些公用方法"><a href="#Object有哪些公用方法" class="headerlink" title="Object有哪些公用方法"></a>Object有哪些公用方法</h3><p>Object是所有类的父类，任何类都默认继承Object<br>clone 保护方法，实现对象的浅复制，只有实现了Cloneable接口才可以调用该方法，否则抛出CloneNotSupportedException异常。<br>equals 在Object中与==是一样的，子类一般需要重写该方法。<br>hashCode 该方法用于哈希查找，重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。<br>getClass final方法，获得运行时类型<br>wait 使当前线程等待该对象的锁，当前线程必须是该对象的拥有者，也就是具有该对象的锁。 wait() 方法一直等待，直到获得锁或者被中断。 wait(long timeout) 设定一个超时间隔，如果在规定时间内没有获得锁就返回。<br>调用该方法后当前线程进入睡眠状态，直到以下事件发生<br>1、其他线程调用了该对象的notify方法。 2、其他线程调用了该对象的notifyAll方法。 3、其他线程调用了interrupt中断该线程。 4、时间间隔到了。 5、此时该线程就可以被调度了，如果是被中断的话就抛出一个InterruptedException异常。<br>notify 唤醒在该对象上等待的某个线程。<br>notifyAll 唤醒在该对象上等待的所有线程。<br>toString 转换成字符串，一般子类都有重写，否则打印句柄。</p>
<h3 id="Java的四种引用，强弱软虚，用到的场景"><a href="#Java的四种引用，强弱软虚，用到的场景" class="headerlink" title="Java的四种引用，强弱软虚，用到的场景"></a>Java的四种引用，强弱软虚，用到的场景</h3><blockquote>
<p>从JDK1.2版本开始，把对象的引用分为四种级别，从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为：强引用、软引用、弱引用和虚引用。</p>
</blockquote>
<ul>
<li>强引用 最普遍的一种引用方式，如String s = “abc”，变量s就是字符串“abc”的强引用，只要强引用存在，则垃圾回收器就不会回收这个对象。</li>
<li>弱引用（WeakReference）弱引用和软引用大致相同，弱引用与软引用的区别在于：只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中，一旦发现了只具有弱引用的对象，不管当前内存空间足够与否，都会回收它的内存。</li>
<li>弱引用（WeakReference）弱引用和软引用大致相同，弱引用与软引用的区别在于：只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中，一旦发现了只具有弱引用的对象，不管当前内存空间足够与否，都会回收它的内存。</li>
<li>虚引用（PhantomReference）就是形同虚设，与其他几种引用都不同，虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用，那么它就和没有任何引用一样，在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。</li>
</ul>
<h3 id="虚引用与软引用和弱引用的一个区别在于："><a href="#虚引用与软引用和弱引用的一个区别在于：" class="headerlink" title="虚引用与软引用和弱引用的一个区别在于："></a>虚引用与软引用和弱引用的一个区别在于：</h3><p>虚引用必须和引用队列 （ReferenceQueue）联合使用。当垃圾回收器准备回收一个对象时，如果发现它还有虚引，就会在回收对象的内存之前，把这个虚引用加入到与之关联的引用队列中。<br>Hashcode的作用</p>
<p><a href="http://blog.csdn.net/seu_calvin/article/details/52094115" target="_blank" rel="noopener">http://blog.csdn.net/seu_calvin/article/details/52094115</a></p>
<ol>
<li>HashCode的特性</li>
</ol>
<p>（1）HashCode的存在主要是用于查找的快捷性，如Hashtable，HashMap等，HashCode经常用于确定对象的存储地址。<br>（2）如果两个对象相同，?equals方法一定返回true，并且这两个对象的HashCode一定相同。<br>（3）两个对象的HashCode相同，并不一定表示两个对象就相同，即equals()不一定为true，只能够说明这两个对象在一个散列存储结构中。<br>（4）如果对象的equals方法被重写，那么对象的HashCode也尽量重写。</p>
<ol>
<li>HashCode作用</li>
</ol>
<p>Java中的集合有两类，一类是List，再有一类是Set。前者集合内的元素是有序的，元素可以重复；后者元素无序，但元素不可重复。<br>equals方法可用于保证元素不重复，但如果每增加一个元素就检查一次，若集合中现在已经有1000个元素，那么第1001个元素加入集合时，就要调用1000次equals方法。这显然会大大降低效率。?于是，Java采用了哈希表的原理。<br>哈希算法也称为散列算法，是将数据依特定算法直接指定到一个地址上。<br>这样一来，当集合要添加新的元素时，先调用这个元素的HashCode方法，就一下子能定位到它应该放置的物理位置上。<br>（1）如果这个位置上没有元素，它就可以直接存储在这个位置上，不用再进行任何比较了。<br>（2）如果这个位置上已经有元素了，就调用它的equals方法与新元素进行比较，相同的话就不存了。<br>（3）不相同的话，也就是发生了Hash key相同导致冲突的情况，那么就在这个Hash key的地方产生一个链表，将所有产生相同HashCode的对象放到这个单链表上去，串在一起（很少出现）。<br>这样一来实际调用equals方法的次数就大大降低了，几乎只需要一两次。<br>如何理解HashCode的作用：<br>从Object角度看，JVM每new一个Object，它都会将这个Object丢到一个Hash表中去，这样的话，下次做Object的比较或者取这个对象的时候（读取过程），它会根据对象的HashCode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。若HashCode相同再去调用equal。<br>3、HashCode实践（如何用来查找）<br>HashCode是用于查找使用的，而equals是用于比较两个对象是否相等的。<br>（1）例如内存中有这样的位置</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">0  1  2  3  4  5  6  7</span><br></pre></td></tr></table></figure>
<p>而我有个类，这个类有个字段叫ID，我要把这个类存放在以上8个位置之一，如果不用HashCode而任意存放，那么当查找时就需要到这八个位置里挨个去找，或者用二分法一类的算法。<br>但以上问题如果用HashCode就会使效率提高很多 定义我们的HashCode为ID％8，比如我们的ID为9，9除8的余数为1，那么我们就把该类存在1这个位置，如果ID是13，求得的余数是5，那么我们就把该类放在5这个位置。依此类推。<br>（2）但是如果两个类有相同的HashCode，例如9除以8和17除以8的余数都是1，也就是说，我们先通过?HashCode来判断两个类是否存放某个桶里，但这个桶里可能有很多类，那么我们就需要再通过equals在这个桶里找到我们要的类。<br>请看下面这个例子</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">public class HashTest &#123;</span><br><span class="line">    private int i;</span><br><span class="line"></span><br><span class="line">    public int <span class="function"><span class="title">getI</span></span>() &#123;</span><br><span class="line">        <span class="built_in">return</span> i;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public void setI(int i) &#123;</span><br><span class="line">        this.i = i;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public int <span class="function"><span class="title">hashCode</span></span>() &#123;</span><br><span class="line">        <span class="built_in">return</span> i % 10;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public final static void main(String[] args) &#123;</span><br><span class="line">        HashTest a = new HashTest();</span><br><span class="line">        HashTest b = new HashTest();</span><br><span class="line">        a.setI(1);</span><br><span class="line">        b.setI(1);</span><br><span class="line">        Set&lt;HashTest&gt; <span class="built_in">set</span> = new HashSet&lt;HashTest&gt;();</span><br><span class="line">        set.add(a);</span><br><span class="line">        set.add(b);</span><br><span class="line">        System.out.println(a.hashCode() == b.hashCode());</span><br><span class="line">        System.out.println(a.equals(b));</span><br><span class="line">        System.out.println(<span class="built_in">set</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">输出结果为：</span><br><span class="line"><span class="literal">true</span></span><br><span class="line">False</span><br><span class="line">[HashTest@1, HashTest@1]</span><br></pre></td></tr></table></figure>
<blockquote>
<p>以上这个示例，我们只是重写了HashCode方法，从上面的结果可以看出，虽然两个对象的HashCode相等，但是实际上两个对象并不是相等，因为我们没有重写equals方法，那么就会调用Object默认的equals方法，显示这是两个不同的对象。<br>这里我们将生成的对象放到了HashSet中，而HashSet中只能够存放唯一的对象，也就是相同的（适用于equals方法）的对象只会存放一个，但是这里实际上是两个对象ab都被放到了HashSet中，这样HashSet就失去了他本身的意义了。</p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line">下面我们继续重写equals方法：</span><br><span class="line">public class HashTest &#123;</span><br><span class="line">    private int i;</span><br><span class="line"></span><br><span class="line">    public int <span class="function"><span class="title">getI</span></span>() &#123;</span><br><span class="line">        <span class="built_in">return</span> i;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public void setI(int i) &#123;</span><br><span class="line">        this.i = i;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public boolean equals(Object object) &#123;</span><br><span class="line">        <span class="keyword">if</span> (object == null) &#123;</span><br><span class="line">            <span class="built_in">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (object == this) &#123;</span><br><span class="line">            <span class="built_in">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (!(object instanceof HashTest)) &#123;</span><br><span class="line">            <span class="built_in">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        HashTest other = (HashTest) object;</span><br><span class="line">        <span class="keyword">if</span> (other.getI() == this.getI()) &#123;</span><br><span class="line">            <span class="built_in">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public int <span class="function"><span class="title">hashCode</span></span>() &#123;</span><br><span class="line">        <span class="built_in">return</span> i % 10;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    public final static void main(String[] args) &#123;</span><br><span class="line">        HashTest a = new HashTest();</span><br><span class="line">        HashTest b = new HashTest();</span><br><span class="line">        a.setI(1);</span><br><span class="line">        b.setI(1);</span><br><span class="line">        Set&lt;HashTest&gt; <span class="built_in">set</span> = new HashSet&lt;HashTest&gt;();</span><br><span class="line">        set.add(a);</span><br><span class="line">        set.add(b);</span><br><span class="line">        System.out.println(a.hashCode() == b.hashCode());</span><br><span class="line">        System.out.println(a.equals(b));</span><br><span class="line">        System.out.println(<span class="built_in">set</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>输出结果如下所示。<br>从结果我们可以看出，现在两个对象就完全相等了，HashSet中也只存放了一份对象。<br>注意：<br>hashCode()只是简单示例写的，真正的生产换将不是这样的</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">true</span></span><br><span class="line"><span class="literal">true</span></span><br><span class="line">[HashTest@1]</span><br></pre></td></tr></table></figure>
<h3 id="HashMap的hashcode的作用"><a href="#HashMap的hashcode的作用" class="headerlink" title="HashMap的hashcode的作用"></a>HashMap的hashcode的作用</h3><p>hashCode的存在主要是用于查找的快捷性，如Hashtable，HashMap等，hashCode是用来在散列存储结构中确定对象的存储地址的。<br>如果两个对象相同，就是适用于equals(java.lang.Object) 方法，那么这两个对象的hashCode一定要相同。<br>如果对象的equals方法被重写，那么对象的hashCode也尽量重写，并且产生hashCode使用的对象，一定要和equals方法中使用的一致，否则就会违反上面提到的第2点。<br>两个对象的hashCode相同，并不一定表示两个对象就相同，也就是不一定适用于equals(java.lang.Object) 方法，只能够说明这两个对象在散列存储结构中，如Hashtable，他们“存放在同一个篮子里”。<br>什么时候需要重写？<br>一般的地方不需要重载hashCode，只有当类需要放在HashTable、HashMap、HashSet等等hash结构的集合时才会重载hashCode，那么为什么要重载hashCode呢？<br>要比较两个类的内容属性值，是否相同时候，根据hashCode 重写规则，重写类的 指定字段的hashCode()，equals()方法。<br>例如:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">public class EmpWorkCondition&#123;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 员工ID</span><br><span class="line">     */</span><br><span class="line">    private Integer empId;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 员工服务总单数</span><br><span class="line">     */</span><br><span class="line">    private Integer orderSum;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public boolean equals(Object o) &#123;</span><br><span class="line">        <span class="keyword">if</span> (this == o) &#123;</span><br><span class="line">            <span class="built_in">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (o == null || getClass() != o.getClass()) &#123;</span><br><span class="line">            <span class="built_in">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        EmpWorkCondition that = (EmpWorkCondition) o;</span><br><span class="line">        <span class="built_in">return</span> Objects.equals(empId, that.empId);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public int <span class="function"><span class="title">hashCode</span></span>() &#123;</span><br><span class="line">        <span class="built_in">return</span> Objects.hash(empId);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // 省略 getter setter</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">public static void main(String[] args) &#123;</span><br><span class="line"></span><br><span class="line">    List&lt;EmpWorkCondition&gt; list1 = new ArrayList&lt;EmpWorkCondition&gt;();</span><br><span class="line"></span><br><span class="line">    EmpWorkCondition emp1 = new EmpWorkCondition();</span><br><span class="line">    emp1.setEmpId(100);</span><br><span class="line">    emp1.setOrderSum(90000);</span><br><span class="line">    list1.add(emp1);</span><br><span class="line"></span><br><span class="line">    List&lt;EmpWorkCondition&gt; list2 = new ArrayList&lt;EmpWorkCondition&gt;();</span><br><span class="line"></span><br><span class="line">    EmpWorkCondition emp2 = new EmpWorkCondition();</span><br><span class="line">    emp2.setEmpId(100);</span><br><span class="line">    list2.add(emp2);</span><br><span class="line"></span><br><span class="line">    System.out.println(list1.contains(emp2));</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">输出结果：<span class="literal">true</span></span><br></pre></td></tr></table></figure>
<p>上面的方法，做的事情就是，比较两个集合中的，实体类对象属性值，是否一致<br>OrderSum 不在比较范围内，因为没有重写它的，equals()和hashCode()方法</p>
<h3 id="为什么要重载equal方法？"><a href="#为什么要重载equal方法？" class="headerlink" title="为什么要重载equal方法？"></a>为什么要重载equal方法？</h3><p>因为Object的equal方法默认是两个对象的引用的比较，意思就是指向同一内存,地址则相等，否则不相等；如果你现在需要利用对象里面的值来判断是否相等，则重载equal方法。</p>
<h3 id="为什么重载hashCode方法？"><a href="#为什么重载hashCode方法？" class="headerlink" title="为什么重载hashCode方法？"></a>为什么重载hashCode方法？</h3><p>一般的地方不需要重载hashCode，只有当类需要放在HashTable、HashMap、HashSet等等hash结构的集合时才会重载hashCode，那么为什么要重载hashCode呢？<br>如果你重写了equals，比如说是基于对象的内容实现的，而保留hashCode的实现不变，那么很可能某两个对象明明是“相等”，而hashCode却不一样。<br>这样，当你用其中的一个作为键保存到hashMap、hasoTable或hashSet中，再以“相等的”找另一个作为键值去查找他们的时候，则根本找不到。<br>为什么equals()相等，hashCode就一定要相等，而hashCode相等，却不要求equals相等?<br>1、因为是按照hashCode来访问小内存块，所以hashCode必须相等。 2、HashMap获取一个对象是比较key的hashCode相等和equal为true。<br>之所以hashCode相等，却可以equal不等，就比如ObjectA和ObjectB他们都有属性name，那么hashCode都以name计算，所以hashCode一样，但是两个对象属于不同类型，所以equal为false。<br>为什么需要hashCode?<br>1、通过hashCode可以很快的查到小内存块。 2、通过hashCode比较比equal方法快，当get时先比较hashCode，如果hashCode不同，直接返回false。</p>
<h3 id="ArrayList、LinkedList、Vector的区别"><a href="#ArrayList、LinkedList、Vector的区别" class="headerlink" title="ArrayList、LinkedList、Vector的区别"></a>ArrayList、LinkedList、Vector的区别</h3><h4 id="List的三个子类的特点"><a href="#List的三个子类的特点" class="headerlink" title="List的三个子类的特点"></a>List的三个子类的特点</h4><h5 id="ArrayList"><a href="#ArrayList" class="headerlink" title="ArrayList"></a>ArrayList</h5><ul>
<li>底层数据结构是数组，查询快，增删慢。</li>
<li>线程不安全，效率高。</li>
</ul>
<p>Vector:</p>
<ul>
<li>底层数据结构是数组，查询快，增删慢。</li>
<li>线程安全，效率低。</li>
<li>Vector相对ArrayList查询慢(线程安全的)。</li>
<li>Vector相对LinkedList增删慢(数组结构)。</li>
</ul>
<p>LinkedList</p>
<ul>
<li>底层数据结构是链表，查询慢，增删快。</li>
<li>线程不安全，效率高。</li>
</ul>
<h5 id="Vector和ArrayList的区别"><a href="#Vector和ArrayList的区别" class="headerlink" title="Vector和ArrayList的区别"></a>Vector和ArrayList的区别</h5><ul>
<li>Vector是线程安全的,效率低。</li>
<li>ArrayList是线程不安全的,效率高。</li>
<li>共同点:底层数据结构都是数组实现的,查询快,增删慢。</li>
</ul>
<h5 id="ArrayList和LinkedList的区别"><a href="#ArrayList和LinkedList的区别" class="headerlink" title="ArrayList和LinkedList的区别"></a>ArrayList和LinkedList的区别</h5><ul>
<li>ArrayList底层是数组结果,查询和修改快。</li>
<li>LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢。</li>
</ul>
<h5 id="共同点-都是线程不安全的"><a href="#共同点-都是线程不安全的" class="headerlink" title="共同点:都是线程不安全的"></a>共同点:都是线程不安全的</h5><p>List有三个子类使用</p>
<ul>
<li>查询多用ArrayList。</li>
<li>增删多用LinkedList。</li>
<li>如果都多ArrayList。</li>
</ul>
<h3 id="String、StringBuffer与StringBuilder的区别"><a href="#String、StringBuffer与StringBuilder的区别" class="headerlink" title="String、StringBuffer与StringBuilder的区别"></a>String、StringBuffer与StringBuilder的区别</h3><blockquote>
<p>String：适用于少量的字符串操作的情况。 StringBuilder：适用于单线程下在字符缓冲区进行大量操作的情况。 StringBuffer：适用多线程下在字符缓冲区进行大量操作的情况。 StringBuilder：是线程不安全的，而StringBuffer是线程安全的。<br>这三个类之间的区别主要是在两个方面，即运行速度和线程安全这两方面。 首先说运行速度，或者说是执行速度，<strong>在这方面运行速度快慢为：StringBuilder &gt; StringBuffer &gt; String。</strong></p>
</blockquote>
<h4 id="String最慢的原因"><a href="#String最慢的原因" class="headerlink" title="String最慢的原因"></a>String最慢的原因</h4><p>String为字符串常量，而StringBuilder和StringBuffer均为字符串变量，即String对象一旦创建之后该对象是不可更改的，但后两者的对象是变量，是可以更改的。<br>再来说线程安全<br>在线程安全上，StringBuilder是线程不安全的，而StringBuffer是线程安全的。<br>如果一个StringBuffer对象在字符串缓冲区被多个线程使用时，StringBuffer中很多方法可以带有synchronized关键字，所以可以保证线程是安全的，但StringBuilder的方法则没有该关键字，所以不能保证线程安全，有可能会出现一些错误的操作。所以如果要进行的操作是多线程的，那么就要使用StringBuffer，但是在单线程的情况下，还是建议使用速度比较快的StringBuilder。</p>
<h3 id="Map、Set、List、Queue、Stack的特点与用法"><a href="#Map、Set、List、Queue、Stack的特点与用法" class="headerlink" title="Map、Set、List、Queue、Stack的特点与用法"></a>Map、Set、List、Queue、Stack的特点与用法</h3><h4 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h4><ul>
<li>Map是键值对，键Key是唯一不能重复的，一个键对应一个值，值可以重复。</li>
<li>TreeMap可以保证顺序。</li>
<li>HashMap不保证顺序，即为无序的。</li>
<li>Map中可以将Key和Value单独抽取出来，其中KeySet()方法可以将所有的keys抽取正一个Set。而Values()方法可以将map中所有的values抽取成一个集合。</li>
</ul>
<h4 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h4><ul>
<li>不包含重复元素的集合，set中最多包含一个null元素。</li>
<li>只能用Lterator实现单项遍历，Set中没有同步方法。</li>
</ul>
<h4 id="List"><a href="#List" class="headerlink" title="List"></a>List</h4><ul>
<li>有序的可重复集合。</li>
<li>可以在任意位置增加删除元素。</li>
<li>用Iterator实现单向遍历，也可用ListIterator实现双向遍历。</li>
</ul>
<h4 id="Queue"><a href="#Queue" class="headerlink" title="Queue"></a>Queue</h4><ul>
<li>Queue遵从先进先出原则。</li>
<li>使用时尽量避免add()和remove()方法,而是使用offer()来添加元素，使用poll()来移除元素，它的优点是可以通过返回值来判断是否成功。</li>
<li>LinkedList实现了Queue接口。</li>
<li>Queue通常不允许插入null元素。</li>
</ul>
<h4 id="Stack"><a href="#Stack" class="headerlink" title="Stack"></a>Stack</h4><ul>
<li>Stack遵从后进先出原则。</li>
<li>Stack继承自Vector。</li>
<li>它通过五个操作对类Vector进行扩展，允许将向量视为堆栈，它提供了通常的push和pop操作，以及取堆栈顶点的peek()方法、测试堆栈是否为空的empty方法等。</li>
</ul>
<h4 id="用法"><a href="#用法" class="headerlink" title="用法"></a>用法</h4><ul>
<li>如果涉及堆栈，队列等操作，建议使用List。</li>
<li>对于快速插入和删除元素的，建议使用LinkedList。</li>
<li>如果需要快速随机访问元素的，建议使用ArrayList。</li>
</ul>
<p>更为精炼的总结<br>Collection 是对象集合， Collection 有两个子接口 List 和 Set<br>List 可以通过下标 (1,2..) 来取得值，值可以重复。 Set 只能通过游标来取值，并且值是不能重复的。<br>ArrayList ， Vector ， LinkedList 是 List 的实现类</p>
<ul>
<li>ArrayList 是线程不安全的， Vector 是线程安全的，这两个类底层都是由数组实现的。</li>
<li>LinkedList 是线程不安全的，底层是由链表实现的。</li>
</ul>
<p>Map 是键值对集合</p>
<ul>
<li>HashTable 和 HashMap 是 Map 的实现类。</li>
<li>HashTable 是线程安全的，不能存储 null 值。</li>
<li>HashMap 不是线程安全的，可以存储 null 值。</li>
</ul>
<p>Stack类：继承自Vector，实现一个后进先出的栈。提供了几个基本方法，push、pop、peak、empty、search等。<br>Queue接口：提供了几个基本方法，offer、poll、peek等。已知实现类有LinkedList、PriorityQueue等。</p>
<h3 id="HashMap和HashTable的区别"><a href="#HashMap和HashTable的区别" class="headerlink" title="HashMap和HashTable的区别"></a>HashMap和HashTable的区别</h3><p><a href="https://segmentfault.com/a/1190000008101567" target="_blank" rel="noopener">https://segmentfault.com/a/1190000008101567</a></p>
<p>Hashtable是基于陈旧的Dictionary类的，HashMap是Java 1.2引进的Map接口的一个实现，它们都是集合中将数据无序存放的。</p>
<ol>
<li>hashMap去掉了HashTable?的contains方法，但是加上了containsValue()和containsKey()方法</li>
</ol>
<p>HashTable Synchronize同步的，线程安全，HashMap不允许空键值为空?，效率低。 HashMap 非Synchronize线程同步的，线程不安全，HashMap允许空键值为空?，效率高。 Hashtable是基于陈旧的Dictionary类的，HashMap是Java 1.2引进的Map接口的一个实现，它们都是集合中将数据无序存放的。<br>Hashtable的方法是同步的，HashMap未经同步，所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样。<br>查看Hashtable的源代码就可以发现，除构造函数外，Hashtable的所有 public 方法声明中都有 synchronized 关键字，而HashMap的源代码中则连 synchronized 的影子都没有，当然，注释除外。</p>
<ol>
<li>Hashtable不允许 null 值(key 和 value 都不可以)，HashMap允许 null 值(key和value都可以)。</li>
<li>两者的遍历方式大同小异，Hashtable仅仅比HashMap多一个elements方法。</li>
</ol>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Hashtable table = new Hashtable();</span><br><span class="line">table.put(<span class="string">"key"</span>, <span class="string">"value"</span>);</span><br><span class="line">Enumeration em = table.elements();</span><br><span class="line"><span class="keyword">while</span> (em.hasMoreElements()) &#123;</span><br><span class="line">   String obj = (String) em.nextElement();</span><br><span class="line">   System.out.println(obj);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>HashTable使用Enumeration，HashMap使用Iterator</p>
<p>从内部机制实现上的区别如下：</p>
<ol>
<li>哈希值的使用不同，Hashtable直接使用对象的hashCode</li>
</ol>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">int <span class="built_in">hash</span> = key.hashCode();</span><br><span class="line">int index = (<span class="built_in">hash</span> &amp; 0x7FFFFFFF) % tab.length;</span><br></pre></td></tr></table></figure>
<p>而HashMap重新计算hash值，而且用与代替求模：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">int <span class="built_in">hash</span> = <span class="built_in">hash</span>(k);</span><br><span class="line">int i = indexFor(<span class="built_in">hash</span>, table.length);</span><br><span class="line"></span><br><span class="line">static int <span class="built_in">hash</span>(Object x) &#123;</span><br><span class="line">&amp;emsp;&amp;emsp;int h = x.hashCode();</span><br><span class="line"></span><br><span class="line">&amp;emsp;&amp;emsp;h += ~(h &lt;&lt; 9);</span><br><span class="line">&amp;emsp;&amp;emsp;h ^= (h &gt;&gt;&gt; 14);</span><br><span class="line">&amp;emsp;&amp;emsp;h += (h &lt;&lt; 4);</span><br><span class="line">&amp;emsp;&amp;emsp;h ^= (h &gt;&gt;&gt; 10);</span><br><span class="line">&amp;emsp;&amp;emsp;<span class="built_in">return</span> h;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">static int indexFor(int h， int length) &#123;</span><br><span class="line">&amp;emsp;&amp;emsp;<span class="built_in">return</span> h &amp; (length-1);</span><br></pre></td></tr></table></figure>
<p> Hashtable中hash数组默认大小是11，增加的方式是 old*2+1。HashMap中hash数组的默认大小是16，而且一定是2的指数。</p>
<h3 id="JDK7与JDK8中HashMap的实现"><a href="#JDK7与JDK8中HashMap的实现" class="headerlink" title="JDK7与JDK8中HashMap的实现"></a>JDK7与JDK8中HashMap的实现</h3><h4 id="JDK7中的HashMap"><a href="#JDK7中的HashMap" class="headerlink" title="JDK7中的HashMap"></a>JDK7中的HashMap</h4><p>HashMap底层维护一个数组，数组中的每一项都是一个Entry。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">transient Entry&lt;K,V&gt;[] table;</span><br></pre></td></tr></table></figure>
<p>我们向 HashMap 中所放置的对象实际上是存储在该数组当中。 而Map中的key，value则以Entry的形式存放在数组中。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">static class Entry&lt;K,V&gt; implements Map.Entry&lt;K,V&gt; &#123;</span><br><span class="line">        final K key;</span><br><span class="line">        V value;</span><br><span class="line">        Entry&lt;K,V&gt; next;</span><br><span class="line">        int <span class="built_in">hash</span>;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>总结一下map.put后的过程：<br>当向 HashMap 中 put 一对键值时，它会根据 key的 hashCode 值计算出一个位置， 该位置就是此对象准备往数组中存放的位置。<br>如果该位置没有对象存在，就将此对象直接放进数组当中；如果该位置已经有对象存在了，则顺着此存在的对象的链开始寻找(为了判断是否是否值相同，map不允许&lt;key,value&gt;键值对重复)， 如果此链上有对象的话，再去使用 equals方法进行比较，如果对此链上的每个对象的 equals 方法比较都为 false，则将该对象放到数组当中，然后将数组中该位置以前存在的那个对象链接到此对象的后面。<br>JDK8中的HashMap<br>JDK8中采用的是位桶+链表/红黑树（有关红黑树请查看红黑树）的方式，也是非线程安全的。当某个位桶的链表的长度达到某个阀值的时候，这个链表就将转换成红黑树。<br>JDK8中，当同一个hash值的节点数不小于8时，将不再以单链表的形式存储了，会被调整成一颗红黑树（上图中null节点没画）。这就是JDK7与JDK8中HashMap实现的最大区别。</p>
</blockquote>
<h4 id="接下来，我们来看下JDK8中HashMap的源码实现。"><a href="#接下来，我们来看下JDK8中HashMap的源码实现。" class="headerlink" title="接下来，我们来看下JDK8中HashMap的源码实现。"></a>接下来，我们来看下JDK8中HashMap的源码实现。</h4><p>JDK中Entry的名字变成了Node，原因是和红黑树的实现TreeNode相关联。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">transient Node&lt;K,V&gt;[] table;</span><br></pre></td></tr></table></figure>
<p>当冲突节点数不小于8-1时，转换成红黑树。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">static final int TREEIFY_THRESHOLD = 8;</span><br></pre></td></tr></table></figure>
<h3 id="HashMap和ConcurrentHashMap的区别，HashMap的底层源码"><a href="#HashMap和ConcurrentHashMap的区别，HashMap的底层源码" class="headerlink" title="HashMap和ConcurrentHashMap的区别，HashMap的底层源码"></a>HashMap和ConcurrentHashMap的区别，HashMap的底层源码</h3><blockquote>
<p>为了线程安全从ConcurrentHashMap代码中可以看出，它引入了一个“分段锁”的概念，具体可以理解为把一个大的Map拆分成N个小的HashTable，根据key.hashCode()来决定把key放到哪个HashTable中。<br>Hashmap本质是数组加链表。根据key取得hash值，然后计算出数组下标，如果多个key对应到同一个下标，就用链表串起来，新插入的在前面。<br>ConcurrentHashMap：在hashMap的基础上，ConcurrentHashMap将数据分为多个segment，默认16个（concurrency level），然后每次操作对一个segment加锁，避免多线程锁的几率，提高并发效率。<br>总结<br>JDK6,7中的ConcurrentHashmap主要使用Segment来实现减小锁粒度，把HashMap分割成若干个Segment，在put的时候需要锁住Segment，get时候不加锁，使用volatile来保证可见性，当要统计全局时（比如size），首先会尝试多次计算modcount来确定，这几次尝试中，是否有其他线程进行了修改操作，如果没有，则直接返回size。如果有，则需要依次锁住所有的Segment来计算。</p>
</blockquote>
<ul>
<li>jdk7中ConcurrentHashmap中，当长度过长碰撞会很频繁，链表的增改删查操作都会消耗很长的时间，影响性能。</li>
<li>jdk8 中完全重写了concurrentHashmap,代码量从原来的1000多行变成了 6000多 行，实现上也和原来的分段式存储有很大的区别。</li>
<li>JDK8中采用的是位桶+链表/红黑树（有关红黑树请查看红黑树）的方式，也是非线程安全的。当某个位桶的链表的长度达到某个阀值的时候，这个链表就将转换成红黑树。</li>
<li>JDK8中，当同一个hash值的节点数不小于8时，将不再以单链表的形式存储了，会被调整成一颗红黑树（上图中null节点没画）。这就是JDK7与JDK8中HashMap实现的最大区别。</li>
</ul>
<h4 id="主要设计上的变化有以下几点"><a href="#主要设计上的变化有以下几点" class="headerlink" title="主要设计上的变化有以下几点"></a>主要设计上的变化有以下几点</h4><ol>
<li>jdk8不采用segment而采用node，锁住node来实现减小锁粒度。 2.设计了MOVED状态 当resize的中过程中 线程2还在put数据，线程2会帮助resize。 3.使用3个CAS操作来确保node的一些操作的原子性，这种方式代替了锁。 4.sizeCtl的不同值来代表不同含义，起到了控制的作用。</li>
</ol>
<blockquote>
<p>至于为什么JDK8中使用synchronized而不是ReentrantLock，我猜是因为JDK8中对synchronized有了足够的优化吧。</p>
</blockquote>
<h4 id="ConcurrentHashMap能完全替代HashTable吗"><a href="#ConcurrentHashMap能完全替代HashTable吗" class="headerlink" title="ConcurrentHashMap能完全替代HashTable吗"></a>ConcurrentHashMap能完全替代HashTable吗</h4><p>hashTable虽然性能上不如ConcurrentHashMap，但并不能完全被取代，两者的迭代器的一致性不同的，hash table的迭代器是强一致性的，而concurrenthashmap是弱一致的。<br>ConcurrentHashMap的get，clear，iterator 都是弱一致性的。 Doug Lea 也将这个判断留给用户自己决定是否使用ConcurrentHashMap。<br>ConcurrentHashMap与HashTable都可以用于多线程的环境，但是当Hashtable的大小增加到一定的时候，性能会急剧下降，因为迭代时需要被锁定很长的时间。因为ConcurrentHashMap引入了分割(segmentation)，不论它变得多么大，仅仅需要锁定map的某个部分，而其它的线程不需要等到迭代完成才能访问map。简而言之，在迭代的过程中，ConcurrentHashMap仅仅锁定map的某个部分，而Hashtable则会锁定整个map。</p>
<h4 id="那么既然ConcurrentHashMap那么优秀，为什么还要有Hashtable的存在呢？ConcurrentHashMap能完全替代HashTable吗？"><a href="#那么既然ConcurrentHashMap那么优秀，为什么还要有Hashtable的存在呢？ConcurrentHashMap能完全替代HashTable吗？" class="headerlink" title="那么既然ConcurrentHashMap那么优秀，为什么还要有Hashtable的存在呢？ConcurrentHashMap能完全替代HashTable吗？"></a>那么既然ConcurrentHashMap那么优秀，为什么还要有Hashtable的存在呢？ConcurrentHashMap能完全替代HashTable吗？</h4><p>HashTable虽然性能上不如ConcurrentHashMap，但并不能完全被取代，两者的迭代器的一致性不同的，HashTable的迭代器是强一致性的，而ConcurrentHashMap是弱一致的。 ConcurrentHashMap的get，clear，iterator 都是弱一致性的。 Doug Lea 也将这个判断留给用户自己决定是否使用ConcurrentHashMap。</p>
<h4 id="那么什么是强一致性和弱一致性呢？"><a href="#那么什么是强一致性和弱一致性呢？" class="headerlink" title="那么什么是强一致性和弱一致性呢？"></a>那么什么是强一致性和弱一致性呢？</h4><blockquote>
<p>get方法是弱一致的，是什么含义？可能你期望往ConcurrentHashMap底层数据结构中加入一个元素后，立马能对get可见，但ConcurrentHashMap并不能如你所愿。换句话说，put操作将一个元素加入到底层数据结构后，get可能在某段时间内还看不到这个元素，若不考虑内存模型，单从代码逻辑上来看，却是应该可以看得到的。<br>下面将结合代码和java内存模型相关内容来分析下put/get方法。put方法我们只需关注Segment#put，get方法只需关注Segment#get，在继续之前，先要说明一下Segment里有两个volatile变量：count和table；HashEntry里有一个volatile变量：value。</p>
</blockquote>
<h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><blockquote>
<p>ConcurrentHashMap的弱一致性主要是为了提升效率，是一致性与效率之间的一种权衡。要成为强一致性，就得到处使用锁，甚至是全局锁，这就与Hashtable和同步的HashMap一样了。</p>
</blockquote>
<h4 id="为什么HashMap是线程不安全的"><a href="#为什么HashMap是线程不安全的" class="headerlink" title="为什么HashMap是线程不安全的"></a>为什么HashMap是线程不安全的</h4><blockquote>
<p>HashMap 在并发执行 put 操作时会引起死循环，导致 CPU 利用率接近100%。因为多线程会导致 HashMap 的 Node 链表形成环形数据结构，一旦形成环形数据结构，Node 的 next 节点永远不为空，就会在获取 Node 时产生死循环。</p>
</blockquote>
<h4 id="如何线程安全的使用HashMap"><a href="#如何线程安全的使用HashMap" class="headerlink" title="如何线程安全的使用HashMap"></a>如何线程安全的使用HashMap</h4><blockquote>
<p>了解了 HashMap 为什么线程不安全，那现在看看如何线程安全的使用 HashMap。这个无非就是以下三种方式：</p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">Hashtable ConcurrentHashMap Synchronized Map</span><br><span class="line">Hashtable</span><br><span class="line">例子</span><br><span class="line">//Hashtable</span><br><span class="line">Map&lt;String, String&gt; hashtable = new Hashtable&lt;&gt;();</span><br><span class="line">//synchronizedMap</span><br><span class="line">Map&lt;String, String&gt; synchronizedHashMap = Collections.synchronizedMap(new HashMap&lt;String, String&gt;());</span><br><span class="line">//ConcurrentHashMap</span><br><span class="line">Map&lt;String, String&gt; concurrentHashMap = new ConcurrentHashMap&lt;&gt;();</span><br><span class="line">Hashtable</span><br><span class="line"></span><br><span class="line">先稍微吐槽一下，为啥命名不是 HashTable 啊，看着好难受不管了就装作它叫HashTable 吧。这货已经不常用了，就简单说说吧。HashTable 源码中是使用?synchronized?来保证线程安全的，比如下面的 get 方法和 put 方法：</span><br><span class="line">public synchronized V get(Object key) &#123;</span><br><span class="line">   // 省略实现</span><br><span class="line">&#125;</span><br><span class="line">public synchronized V put(K key, V value) &#123;</span><br><span class="line">// 省略实现</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>所以当一个线程访问 HashTable 的同步方法时，其他线程如果也要访问同步方法，会被阻塞住。举个例子，当一个线程使用 put 方法时，另一个线程不但不可以使用 put 方法，连 get 方法都不可以，好霸道啊！！！so~~，效率很低，现在基本不会选择它了。<br>ConcurrentHashMap<br>ConcurrentHashMap 于 Java 7 的，和8有区别,在8中 CHM 摒弃了 Segment（锁段）的概念，而是启用了一种全新的方式实现,利用 CAS 算法，有时间会重新总结一下。<br>SynchronizedMap<br>synchronizedMap() 方法后会返回一个 SynchronizedMap 类的对象，而在 SynchronizedMap 类中使用了 synchronized 同步关键字来保证对 Map 的操作是线程安全的。<br>性能对比<br>这是要靠数据说话的时代，所以不能只靠嘴说 CHM 快，它就快了。写个测试用例，实际的比较一下这三种方式的效率(源码来源)，下面的代码分别通过三种方式创建 Map 对象，使用 ExecutorService 来并发运行5个线程，每个线程添加/获取500K个元素。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">Test started <span class="keyword">for</span>: class java.util.Hashtable</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 2018 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1746 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1806 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1801 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1804 ms</span><br><span class="line">For class java.util.Hashtable the average time is 1835 ms</span><br><span class="line"></span><br><span class="line">Test started <span class="keyword">for</span>: class java.util.Collections<span class="variable">$SynchronizedMap</span></span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 3041 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1690 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1740 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1649 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1696 ms</span><br><span class="line">For class java.util.Collections<span class="variable">$SynchronizedMap</span> the average time is 1963 ms</span><br><span class="line"></span><br><span class="line">Test started <span class="keyword">for</span>: class java.util.concurrent.ConcurrentHashMap</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 738 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 696 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 548 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 1447 ms</span><br><span class="line">2500K entried added/retrieved <span class="keyword">in</span> 531 ms</span><br><span class="line">For class java.util.concurrent.ConcurrentHashMap the average time is 792 ms</span><br></pre></td></tr></table></figure>
<p>ConcurrentHashMap 性能是明显优于 Hashtable 和 SynchronizedMap 的,CHM 花费的时间比前两个的一半还少。</p>
<h3 id="多并发情况下HashMap是否还会产生死循环"><a href="#多并发情况下HashMap是否还会产生死循环" class="headerlink" title="多并发情况下HashMap是否还会产生死循环"></a>多并发情况下HashMap是否还会产生死循环</h3><blockquote>
<p>今天本来想看下了ConcurrentHashMap的源码，ConcurrentHashMap是Java 5中支持高并发、高吞吐量的线程安全HashMap实现。<br>在看很多博客在介绍ConcurrentHashMap之前，都说HashMap适用于单线程访问，这是因为HashMap的所有方法都没有进行锁同步，因此是线程不安全的，不仅如此，当多线程访问的时候还容易产生死循环。</p>
</blockquote>
<p>虽然自己在前几天的时候看过HashMap的源码，感觉思路啥啥的都还清楚，对于多线程访问只知道HashMap是线程不安全的，但是不知道HashMap在多线程并发的情况下会产生死循环呢，为什么会产生,何种情况下才会产生死循环呢？？？</p>
<p>《Java困惑》：多并发情况下HashMap是否还会产生死循环。<br>blog.csdn.net/u010412719/…</p>
<blockquote>
<p>既然会产生死循环，为什么并发情况下，还是用ConcurrentHashMap。 jdk 好像有，但是Jdk8 已经修复了这个问题。<br>内容转载自：<a href="https://juejin.im/post/5aa3ea686fb9a028c522cda5" target="_blank" rel="noopener">https://juejin.im/post/5aa3ea686fb9a028c522cda5</a></p>
</blockquote>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2018/10/23/Java面试：String，StringBuilder，StringBuffer三者的区别/" rel="next" title="Java面试：String，StringBuilder，StringBuffer三者的区别">
                <i class="fa fa-chevron-left"></i> Java面试：String，StringBuilder，StringBuffer三者的区别
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2018/10/27/Java基础之理论知识/" rel="prev" title="Java基础之理论知识">
                Java基础之理论知识 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/avatar.gif" alt="四 季">
            
              <p class="site-author-name" itemprop="name">四 季</p>
              <p class="site-description motion-element" itemprop="description">我的学习笔记站</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">15</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            

            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#由于答案字数较多，已将此面试题分为上、下两级，此为上集。"><span class="nav-number">1.</span> <span class="nav-text">由于答案字数较多，已将此面试题分为上、下两级，此为上集。</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#八种基本数据类型的大小，以及他们的封装类"><span class="nav-number">1.1.</span> <span class="nav-text">八种基本数据类型的大小，以及他们的封装类</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#引用数据类型"><span class="nav-number">1.1.1.</span> <span class="nav-text">引用数据类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Switch能否用string做参数"><span class="nav-number">1.1.2.</span> <span class="nav-text">Switch能否用string做参数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#为什么jdk1-7后又可以用string类型作为switch参数呢？"><span class="nav-number">1.1.3.</span> <span class="nav-text">为什么jdk1.7后又可以用string类型作为switch参数呢？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#equals与-的区别"><span class="nav-number">1.1.4.</span> <span class="nav-text">equals与==的区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自动装箱，常量池"><span class="nav-number">1.1.5.</span> <span class="nav-text">自动装箱，常量池</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自动拆箱和自动装箱定义："><span class="nav-number">1.1.6.</span> <span class="nav-text">自动拆箱和自动装箱定义：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Object有哪些公用方法"><span class="nav-number">1.1.7.</span> <span class="nav-text">Object有哪些公用方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Java的四种引用，强弱软虚，用到的场景"><span class="nav-number">1.1.8.</span> <span class="nav-text">Java的四种引用，强弱软虚，用到的场景</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#虚引用与软引用和弱引用的一个区别在于："><span class="nav-number">1.1.9.</span> <span class="nav-text">虚引用与软引用和弱引用的一个区别在于：</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HashMap的hashcode的作用"><span class="nav-number">1.1.10.</span> <span class="nav-text">HashMap的hashcode的作用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#为什么要重载equal方法？"><span class="nav-number">1.1.11.</span> <span class="nav-text">为什么要重载equal方法？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#为什么重载hashCode方法？"><span class="nav-number">1.1.12.</span> <span class="nav-text">为什么重载hashCode方法？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ArrayList、LinkedList、Vector的区别"><span class="nav-number">1.1.13.</span> <span class="nav-text">ArrayList、LinkedList、Vector的区别</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#List的三个子类的特点"><span class="nav-number">1.1.13.1.</span> <span class="nav-text">List的三个子类的特点</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#ArrayList"><span class="nav-number">1.1.13.1.1.</span> <span class="nav-text">ArrayList</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Vector和ArrayList的区别"><span class="nav-number">1.1.13.1.2.</span> <span class="nav-text">Vector和ArrayList的区别</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#ArrayList和LinkedList的区别"><span class="nav-number">1.1.13.1.3.</span> <span class="nav-text">ArrayList和LinkedList的区别</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#共同点-都是线程不安全的"><span class="nav-number">1.1.13.1.4.</span> <span class="nav-text">共同点:都是线程不安全的</span></a></li></ol></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#String、StringBuffer与StringBuilder的区别"><span class="nav-number">1.1.14.</span> <span class="nav-text">String、StringBuffer与StringBuilder的区别</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#String最慢的原因"><span class="nav-number">1.1.14.1.</span> <span class="nav-text">String最慢的原因</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Map、Set、List、Queue、Stack的特点与用法"><span class="nav-number">1.1.15.</span> <span class="nav-text">Map、Set、List、Queue、Stack的特点与用法</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Map"><span class="nav-number">1.1.15.1.</span> <span class="nav-text">Map</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Set"><span class="nav-number">1.1.15.2.</span> <span class="nav-text">Set</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#List"><span class="nav-number">1.1.15.3.</span> <span class="nav-text">List</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Queue"><span class="nav-number">1.1.15.4.</span> <span class="nav-text">Queue</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Stack"><span class="nav-number">1.1.15.5.</span> <span class="nav-text">Stack</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#用法"><span class="nav-number">1.1.15.6.</span> <span class="nav-text">用法</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HashMap和HashTable的区别"><span class="nav-number">1.1.16.</span> <span class="nav-text">HashMap和HashTable的区别</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#JDK7与JDK8中HashMap的实现"><span class="nav-number">1.1.17.</span> <span class="nav-text">JDK7与JDK8中HashMap的实现</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#JDK7中的HashMap"><span class="nav-number">1.1.17.1.</span> <span class="nav-text">JDK7中的HashMap</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#接下来，我们来看下JDK8中HashMap的源码实现。"><span class="nav-number">1.1.17.2.</span> <span class="nav-text">接下来，我们来看下JDK8中HashMap的源码实现。</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#HashMap和ConcurrentHashMap的区别，HashMap的底层源码"><span class="nav-number">1.1.18.</span> <span class="nav-text">HashMap和ConcurrentHashMap的区别，HashMap的底层源码</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#主要设计上的变化有以下几点"><span class="nav-number">1.1.18.1.</span> <span class="nav-text">主要设计上的变化有以下几点</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#ConcurrentHashMap能完全替代HashTable吗"><span class="nav-number">1.1.18.2.</span> <span class="nav-text">ConcurrentHashMap能完全替代HashTable吗</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#那么既然ConcurrentHashMap那么优秀，为什么还要有Hashtable的存在呢？ConcurrentHashMap能完全替代HashTable吗？"><span class="nav-number">1.1.18.3.</span> <span class="nav-text">那么既然ConcurrentHashMap那么优秀，为什么还要有Hashtable的存在呢？ConcurrentHashMap能完全替代HashTable吗？</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#那么什么是强一致性和弱一致性呢？"><span class="nav-number">1.1.18.4.</span> <span class="nav-text">那么什么是强一致性和弱一致性呢？</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#总结"><span class="nav-number">1.1.18.5.</span> <span class="nav-text">总结</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#为什么HashMap是线程不安全的"><span class="nav-number">1.1.18.6.</span> <span class="nav-text">为什么HashMap是线程不安全的</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#如何线程安全的使用HashMap"><span class="nav-number">1.1.18.7.</span> <span class="nav-text">如何线程安全的使用HashMap</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#多并发情况下HashMap是否还会产生死循环"><span class="nav-number">1.1.19.</span> <span class="nav-text">多并发情况下HashMap是否还会产生死循环</span></a></li></ol></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">四 季</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Pisces</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
